package com.pubinfo.passbook.data.quartz.utils;

import com.pubinfo.passbook.common.entity.TAutoTask;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 计划任务管理
 *
 * @author litiewang
 * @website www.laoyeye.net
 */
@Slf4j
@Service
public class QuartzManager {
  
  @Autowired
  private Scheduler scheduler;
  
  private final String beanClass = "com.auto.test.quartz.task.AutoTestJob";
  
  /**
   * 添加任务
   *
   * @throws SchedulerException
   */
  @SuppressWarnings("unchecked")
  public void addJob(TAutoTask task) {
    try {
      // 创建jobDetail实例，绑定Job实现类
      // 指明job的名称，所在组的名称，以及绑定job类
      Class<? extends Job> jobClass = (Class<? extends Job>) (Class.forName(task.getBeanClass()).newInstance()
          .getClass());
      JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(task.getName(), task.getGroupName())// 任务名称和组构成任务key
          .build();
      jobDetail.getJobDataMap().put("task-id", task.getId());
      
      // 定义调度触发规则
      // 使用cornTrigger规则
      Trigger trigger = TriggerBuilder.newTrigger().withIdentity(task.getName(), task.getGroupName())// 触发器key
          .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
          .withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())).startNow().build();
      // 把作业和触发器注册到任务调度中
      scheduler.scheduleJob(jobDetail, trigger);
      // 启动
      if (!scheduler.isShutdown()) {
        scheduler.start();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  /**
   * 获取所有计划中的任务列表
   *
   * @return
   * @throws SchedulerException
   */
  public List<TAutoTask> getAllJob() throws SchedulerException {
    GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
    Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
    List<TAutoTask> jobList = new ArrayList<TAutoTask>();
    for (JobKey jobKey : jobKeys) {
      List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
      for (Trigger trigger : triggers) {
        TAutoTask job = new TAutoTask();
        job.setName(jobKey.getName());
        job.setRemark(jobKey.getGroup());
        job.setRemark("触发器:" + trigger.getKey());
        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
        
        job.setStatus(triggerState.name());
        if (trigger instanceof CronTrigger) {
          CronTrigger cronTrigger = (CronTrigger) trigger;
          String cronExpression = cronTrigger.getCronExpression();
          job.setCronExpression(cronExpression);
        }
        jobList.add(job);
      }
    }
    return jobList;
  }
  
  /**
   * 所有正在运行的job
   *
   * @return
   * @throws SchedulerException
   */
  public List<TAutoTask> getRunningJob() throws SchedulerException {
    List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
    List<TAutoTask> jobList = new ArrayList<TAutoTask>(executingJobs.size());
    for (JobExecutionContext executingJob : executingJobs) {
      TAutoTask job = new TAutoTask();
      JobDetail jobDetail = executingJob.getJobDetail();
      JobKey jobKey = jobDetail.getKey();
      Trigger trigger = executingJob.getTrigger();
      job.setName(jobKey.getName());
      
      job.setRemark("触发器:" + trigger.getKey());
      Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
      job.setStatus(triggerState.name());
      if (trigger instanceof CronTrigger) {
        CronTrigger cronTrigger = (CronTrigger) trigger;
        String cronExpression = cronTrigger.getCronExpression();
        job.setCronExpression(cronExpression);
      }
      jobList.add(job);
    }
    return jobList;
  }
  
  /**
   * 暂停一个job
   *
   * @param task
   * @throws SchedulerException
   */
  public void pauseJob(TAutoTask task) throws SchedulerException {
    JobKey jobKey = JobKey.jobKey(task.getName(), task.getGroupName());
    scheduler.pauseJob(jobKey);
  }
  
  /**
   * 恢复一个job
   *
   * @param task
   * @throws SchedulerException
   */
  public void resumeJob(TAutoTask task) throws SchedulerException {
    JobKey jobKey = JobKey.jobKey(task.getName(), task.getGroupName());
    scheduler.resumeJob(jobKey);
  }
  
  /**
   * 删除一个job
   *
   * @param task
   * @throws SchedulerException
   */
  public void deleteJob(TAutoTask task) throws SchedulerException {
    JobKey jobKey = JobKey.jobKey(task.getName(), task.getGroupName());
    scheduler.deleteJob(jobKey);
  }
  
  /**
   * 立即执行job
   *
   * @param task
   * @throws SchedulerException
   */
  public void runJobNow(TAutoTask task) throws SchedulerException {
    JobKey jobKey = JobKey.jobKey(task.getName(), task.getGroupName());
    scheduler.triggerJob(jobKey);
  }
  
  /**
   * 更新job时间表达式
   *
   * @param task
   * @throws SchedulerException
   */
  public void updateJobCron(TAutoTask task) throws SchedulerException {
    TriggerKey triggerKey = TriggerKey.triggerKey(task.getName(), task.getGroupName());
    CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCronExpression());
    trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
    scheduler.rescheduleJob(triggerKey, trigger);
  }
}